package com.blog.dao.base;

import com.blog.beans.PageBean;
import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * Generic DAO Interface
 * Created with IntelliJ IDEA.
 * Author:  Wu Yujie
 * Email:  coffee377@dingtalk.com
 * Time:  2016/12/26 19:29
 *
 * @param <E> instance of the generic entity class
 */
public interface Dao<E> {

    SessionFactory getSessionFactory();

    Session getSession();

    /**
     * 保存实体
     *
     * @param entity 业务实体对象
     * @return 保存成功后返回对象主键值，否则返回 -1
     */
    Serializable save(E entity);

    /**
     * 持久化实体
     *
     * @param entity 业务实体对象
     */
    void persist(E entity);

    /**
     * Remove a persistent instance from the datastore.
     *
     * @param entity the instance to be removed
     */
    void delete(E entity);


    /**
     * 删除多个实体
     *
     * @param entities 实体对象集合
     */
    void deleteAll(Collection<?> entities);

    /**
     * Update the persistent instance with the identifier
     * of the given detached instance. If there is a persistent
     * instance with the same identifier, an exception is thrown.
     *
     * @param entity a detached instance containing updated state
     */
    void update(E entity);

    /**
     * Copy the state of the given object onto the persistent object
     * with the same identifier. If there is no persistent instance
     * currently associated with the session, it will be loaded.
     * Return the persistent instance. If the given instance is unsaved,
     * save a copy of and return it as a newly persistent instance.
     *
     * @param entity a detached instance with state to be copied
     * @return an updated persistent instance
     */
    E merge(E entity);

    /**
     * Return the persistent instance of the generic entity class
     * with the given identifier, or null if there is no such
     * persistent instance.
     *
     * @param id an identifier
     * @return a persistent instance or null
     */
    E get(Serializable id);

    /**
     * Return the persistent instance of the generic entity class
     * with the given identifier, or null if there is no such
     * persistent instance
     *
     * @param id          an identifier
     * @param lockOptions the lock mode
     * @return a persistent instance or null
     */
    E get(Serializable id, LockOptions lockOptions);

    /**
     * Return the persistent instance of the generic entity class
     * with the given identifier, assuming that the instance exists.
     *
     * @param id a valid identifier of an existing persistent
     *           instance of the class
     * @return the persistent instance or proxy
     */
    E load(Serializable id);

    /**
     * Return the persistent instance of the generic entity class with
     * the given identifier, obtaining the specified lock mode,
     * assuming the instance exists.
     *
     * @param id          a valid identifier of an existing persistent
     *                    instance of the class
     * @param lockOptions contains the lock level
     * @return the persistent instance or proxy
     */
    E load(Serializable id, LockOptions lockOptions);

    /**
     * 当前 Session 是否存在指定的实体
     *
     * @param entity 实体对象
     * @return 存在返回 TRUE 否则返回 FALSE
     */
    boolean contains(E entity);


    /**
     * 查询多条记录
     *
     * @param hql    占位符 HQL 语句
     * @param params 可变参数
     * @return 返回业务对象集合
     */
    List<E> find(String hql, Object... params);

    /**
     * 分页查找业务实体对象
     *
     * @param pageNumber 页码
     * @param pageSize   每页记录数
     * @param hql        占位符 HQL 语句
     * @param params     可变参数
     * @return 当前页的业务实体对象的集合
     */
    List<E> find(int pageNumber, int pageSize, String hql, Object... params);

    /**
     * Hibernate 条件分页查询
     *
     * @param pageNumber 页码
     * @param pageSize   每页记录数
     * @param criteria   条件接口
     * @return 符合要求当前页的业务实体对象集合
     */
    List<E> findByCriteria(int pageNumber, int pageSize, Criteria criteria);

    /**
     * Hibernate 条件查询
     *
     * @param criteria 条件接口
     * @return 符合要求的业务实体对象集合
     */
    List<E> findByCriteria(Criteria criteria);

    /**
     * Hibernate 离线条件分页查询
     *
     * @param pageNumber       页码
     * @param pageSize         每页记录数
     * @param detachedCriteria 离线条件对象
     * @return 符合要求当前页的业务实体对象集合
     */
    List<E> findByDetachedCriteria(int pageNumber, int pageSize, DetachedCriteria detachedCriteria);

    /**
     * Hibernate 离线条件查询
     *
     * @param detachedCriteria 离线条件对象
     * @return 符合要求的业务实体对象集合
     */
    List<E> findByDetachedCriteria(DetachedCriteria detachedCriteria);

    /**
     * 获取记录数
     *
     * @param hql    占位符 HQL/SQL 语句
     * @param params 可变参数
     * @return 记录数量
     */
    Integer getCount(String hql, Object... params);

    /**
     * Hibernate 在线获取记录数
     *
     * @param criteria 条件接口
     * @return 记录数量
     */
    Integer getCount(Criteria criteria);

    /**
     * Hibernate 离线获取记录数
     *
     * @param detachedCriteria 离线条件对象
     * @return 记录数量
     */
    Integer getCount(DetachedCriteria detachedCriteria);

    /**
     * 分页查询
     *
     * @param pageNumber 页码
     * @param pageSize   每页记录数
     * @param hql        占位符 HQL/SQL 语句
     * @param params     可变参数
     * @return 当前页对象 PageBean<E>
     */
    PageBean<E> findForPage(int pageNumber, int pageSize, String hql, Object... params);

    /**
     * Hibernate 分页查询
     *
     * @param pageNumber 页码
     * @param pageSize   每页记录数
     * @param criteria   条件接口
     * @return 符合要求当前页对象 PageBean<E>
     */
    PageBean<E> findForPage(int pageNumber, int pageSize, Criteria criteria);


    /**
     * Hibernate 离线条件分页查询
     *
     * @param pageNumber       页码
     * @param pageSize         每页记录数
     * @param detachedCriteria 离线条件对象
     * @return 符合要求当前页对象 PageBean<E>
     */
    PageBean<E> findForPage(int pageNumber, int pageSize, DetachedCriteria detachedCriteria);


}

